/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.lcm.metadata.core;

import com.inspur.edp.lcm.metadata.common.Utils;
import com.inspur.edp.lcm.metadata.common.configuration.MetadataServiceHelper;
import com.inspur.edp.lcm.metadata.core.dao.MdRecentOpDao;
import com.inspur.edp.lcm.metadata.core.domain.GspMdRecentOp;
import com.inspur.edp.lcm.metadata.devcommon.ManagerUtils;
import com.inspur.edp.lcm.metadata.inner.api.WsService;
import com.inspur.edp.lcm.metadata.inner.api.utils.WsUtils;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.util.CollectionUtils;

/**
 * 用户最近打开元数据操作服务类
 */
@Slf4j
public class MdRecentOpService {
    private MdRecentOpDao mdRecentOpDao;
    private String fileName = "config/platform/common/lcm_metadatarecentop.json";
    private String sectionName = "showMdTypeList";
    /**
     * 记录用户打开元数据操作信息
     *
     * @param mdPath 元数据全路径
     * @param mdCode 元数据编号
     * @param mdName 元数据名称
     * @param boId   业务对象id
     */
    public void saveMdRecentOp(String mdPath, String mdCode, String mdName, String boId) {
        if (Objects.isNull(mdPath) || Objects.isNull(mdCode) || Objects.isNull(mdName) || Objects.isNull(boId)) {
            log.warn("保存用户最近打开信息错误,参数不能为空。mdPath:{},mdCode:{},mdName:{},boID:{}", mdPath, mdCode, mdName, boId);
            return;
        }
        // 先根据元数据全路径、用户id、工作空间id、业务对象id判断此元数据是否已经添加过，已经添加过的只需要更新记录即可
        String wsId = null;
        WsService wsService = WsUtils.getWsService();
        if (Objects.nonNull(wsService)) {
            wsId = wsService.getActiveWorkSpaceId();
        }
        String userId = CAFContext.current.getUserId();
        LocalDateTime time = LocalDateTime.now();
        GspMdRecentOp gspMdRecentOpQuery = new GspMdRecentOp();
        gspMdRecentOpQuery.setUserId(userId)
            .setWsId(wsId)
            .setBoID(boId)
            .setMdPath(mdPath);
        Optional<GspMdRecentOp> gspMdRecentOpOptional = getMdRecentOpDao().findOne(Example.of(gspMdRecentOpQuery));
        if (gspMdRecentOpOptional.isPresent()) {
            GspMdRecentOp gspMdRecentOpForUpdate = gspMdRecentOpOptional.get();
            gspMdRecentOpForUpdate.setMdCode(mdCode).setMdName(mdName).setLastModifiedTime(time);
            getMdRecentOpDao().save(gspMdRecentOpForUpdate);
            return;
        }

        // 一个用户在一个bo下允许记录的最近打开最大条数为20，超过20则覆盖时间最早的
        GspMdRecentOp gspMdRecentOpForQuery = new GspMdRecentOp();
        gspMdRecentOpForQuery.setUserId(userId)
            .setWsId(wsId)
            .setBoID(boId);
        List<GspMdRecentOp> gspMdRecentOpList = getMdRecentOpDao().findAll(Example.of(gspMdRecentOpForQuery));
        if (!CollectionUtils.isEmpty(gspMdRecentOpList) && gspMdRecentOpList.size() >= 20) {
            List<GspMdRecentOp> gspMdRecentOpSortedList = gspMdRecentOpList.stream().sorted(Comparator.comparing(GspMdRecentOp::getLastModifiedTime)).collect(Collectors.toList());
            GspMdRecentOp gspMdRecentOpForUpdate = gspMdRecentOpSortedList.get(0);
            gspMdRecentOpForUpdate.setMdPath(mdPath).setMdCode(mdCode).setMdName(mdName).setLastModifiedTime(time).setLastModifiedTime(time);
            getMdRecentOpDao().save(gspMdRecentOpForUpdate);
            return;
        }
        GspMdRecentOp gspMdRecentOp = new GspMdRecentOp();
        gspMdRecentOp.setId(UUID.randomUUID().toString())
            .setUserId(userId)
            .setWsId(wsId)
            .setBoID(boId)
            .setMdCode(mdCode)
            .setMdName(mdName)
            .setMdPath(mdPath)
            .setCreatedTime(time)
            .setLastModifiedTime(time);
        getMdRecentOpDao().save(gspMdRecentOp);
    }

    /**
     * 获取用户最近操作列表
     *
     * @param boId 业务对象id
     * @return
     */
    public List<GspMdRecentOp> getRecnetMdOp(String boId) {
        if (Objects.isNull(boId)) {
            return null;
        }
        String wsId = null;
        WsService wsService = WsUtils.getWsService();
        if (Objects.nonNull(wsService)) {
            wsId = wsService.getActiveWorkSpaceId();
        }
        GspMdRecentOp gspMdRecentOpQuery = new GspMdRecentOp();
        gspMdRecentOpQuery.setUserId(CAFContext.current.getUserId())
            .setWsId(wsId)
            .setBoID(boId);
        List<GspMdRecentOp> gspMdRecentOpList = getMdRecentOpDao().findAll(Example.of(gspMdRecentOpQuery));
        if (CollectionUtils.isEmpty(gspMdRecentOpList)) {
            return null;
        }

        //根据可新建的元数据类型过滤
        List<String> typeList = loadShowMdRecentOpTypeList();
        return gspMdRecentOpList.stream().filter(opInfo -> typeList.contains(opInfo.getMdPath().substring(opInfo.getMdPath().lastIndexOf(".")))).sorted(Comparator.comparing(GspMdRecentOp::getLastModifiedTime).reversed()).collect(Collectors.toList());
    }

    /**
     * 校验元数据是否存在
     *
     * @param metadataFullPath 元数据全路径
     * @return
     */
    public boolean isValidRecentMdOp(String metadataFullPath) {
        if (Objects.isNull(metadataFullPath)) {
            return false;
        }
        return Files.exists(Paths.get(ManagerUtils.getAbsolutePath(metadataFullPath)));
    }

    /**
     * 删除用户操作信息
     *
     * @param recentMdOpId 用户最近操作id
     * @return
     */
    public void deleteRecentMdOpById(String recentMdOpId) {
        if (Objects.isNull(recentMdOpId)) {
            return;
        }
        if(getMdRecentOpDao().existsById(recentMdOpId)) {
            getMdRecentOpDao().deleteById(recentMdOpId);
        }
    }

    private MdRecentOpDao getMdRecentOpDao() {
        if (Objects.isNull(mdRecentOpDao)) {
            mdRecentOpDao = SpringBeanUtils.getBean(MdRecentOpDao.class);
        }
        return mdRecentOpDao;
    }
    protected List<String> loadShowMdRecentOpTypeList() {
        try {
            return MetadataServiceHelper.getConfigurationList(Utils.getAbsoluteConfigFilePath(fileName), sectionName, String.class);
        } catch (IOException e) {
            throw new RuntimeException("读取配置文件失败：" + fileName, e);
        }
    }
}
